package org.example.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.example.myEnum.ErrorCode;
import org.example.util.JwtTokenUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;


public class JwtAuthenticationFilter extends OncePerRequestFilter {

    private static final Logger logger = LoggerFactory.getLogger(JwtAuthenticationFilter.class);
    private final RedisTemplate<String, Object> redisTemplate;
    private final ObjectMapper objectMapper = new ObjectMapper();

    public JwtAuthenticationFilter(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, 
                                   HttpServletResponse response, 
                                   FilterChain filterChain) throws ServletException, IOException {

        // 如果是预检请求，直接返回 200
        if ("OPTIONS".equals(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
            return;
        }

        try {
            // 添加调试日志
            logger.debug("Request URI: {}", request.getRequestURI());
            logger.debug("Authorization header: {}", request.getHeader("Authorization"));

            String requestURI = request.getRequestURI();

            // 1. 检查是否是无需验证的路径
            if (isPermitAll(request)) {
                logger.debug("Permit all path, skipping token validation for: {}", requestURI);
                filterChain.doFilter(request, response);
                return;
            }

            // 2. 从请求头获取Token
            String token = resolveToken(request);
            logger.debug("Resolved token: {}", token);
            
            logger.debug("Processing request for URI: {}", requestURI);
            


            // 3. Token不存在
            if (token == null) {
                logger.warn("No token found in request for URI: {}", requestURI);
                handleAuthenticationError(response, ErrorCode.TOKEN_NOT_FOUND);
                return;
            }

            // 4. 验证Token是否有效
            if (!JwtTokenUtil.validateToken(token)) {
                logger.warn("Invalid token for URI: {}", requestURI);
                handleAuthenticationError(response, ErrorCode.TOKEN_INVALID);
                return;
            }

            // 5. 检查Token是否过期
            if (JwtTokenUtil.isTokenExpired(token)) {
                logger.warn("Token expired for URI: {}", requestURI);
                handleAuthenticationError(response, ErrorCode.TOKEN_OUT_OF_TIME);
                return;
            }

            // 6. 检查Redis中是否存在该Token（用于实现token注销功能）
            if (Boolean.FALSE.equals(redisTemplate.hasKey(token))) {
                logger.warn("Token not found in Redis for URI: {}", requestURI);
                handleAuthenticationError(response, ErrorCode.TOKEN_OUT_OF_TIME);
                return;
            }

            // 7. 获取用户信息并设置到请求属性中（如果需要）
            String username = JwtTokenUtil.getUsernameFromToken(token);
            request.setAttribute("username", username);
            
            logger.debug("Token validation successful for user: {} on URI: {}", username, requestURI);
            
            // 8. 放行请求
            filterChain.doFilter(request, response);
            
        } catch (Exception e) {
            logger.error("Unexpected error during authentication", e);
            handleAuthenticationError(response, ErrorCode.TOKEN_INVALID);
        }
    }

    private void handleAuthenticationError(HttpServletResponse response, ErrorCode errorCode) throws IOException {
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.setCharacterEncoding("UTF-8");
        
        Map<String, Object> errorResponse = new HashMap<>();
        errorResponse.put("code", errorCode.getCode());
        errorResponse.put("message", errorCode.getMessage());
        
        objectMapper.writeValue(response.getWriter(), errorResponse);
    }

    private String resolveToken(HttpServletRequest request) {
        // 获取所有可能的Authorization头
        String bearerToken = request.getHeader("Authorization");
        if (bearerToken == null) {
            bearerToken = request.getHeader("authorization");
        }
        
        if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
            // 去除可能的空格
            return bearerToken.substring(7).trim();
        }
        return null;
    }

    private boolean isPermitAll(HttpServletRequest request) {
        String uri = request.getRequestURI();
        return uri.equals("/api/user/login") ||  // 修改为精确匹配
               uri.startsWith("/error") ||
               uri.startsWith("/swagger") ||
               uri.startsWith("/api/user/register") ||
               uri.startsWith("/api/public");
    }
}